<template>
  <div class="sort-container">
    <template v-for="node in sortedNodes" :key="node.key">
      <component :is="node" />
    </template>
  </div>
</template>

<script lang="tsx" setup>
import { computed, useSlots } from 'vue'

interface IProps {
  sortKey: string
  orders: string[]
  filter?: (node: any) => boolean
}
const props = withDefaults(defineProps<IProps>(), {
  orders: () => [],
  filter: () => () => true,
})

const slots = useSlots()

const sortedNodes = computed(() => {
  const orders = props.orders
  const orderMap = new Map(orders.map((value, index) => [value, index]))

  return slots
    .default?.()
    .filter((node) => typeof node.type === 'object')
    .filter((node) => props.filter(node))
    .map((node) => ({
      node,
      orderIndex: orderMap.get(node.props?.[props.sortKey]) ?? Infinity,
    }))
    .sort((a, b) => a.orderIndex - b.orderIndex)
    .map((item) => item.node)
})
</script>
